package org.fastsyncer.manager.splitter.impl;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.manager.splitter.Splitter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//声明一个final，使别人不能随便new对象
//它只被调用一次，实例存在之后就不再调用了
public final class SqlServerSplitter implements Splitter {

    // 实现单例模式的方法，通过方法来实现实例化
    // 声明一个私有的静态属性，使只被实例化一次
    private static volatile SqlServerSplitter instance = null;

    private SqlServerSplitter() {
    }

    // 声明一个公共的静态方法，外界通过调用这个方法来得到唯一的实例
    public static SqlServerSplitter getInstance() {
        if (null == instance) {
            synchronized (SqlServerSplitter.class) {
                if (null == instance) {
                    instance = new SqlServerSplitter();
                }
            }
        }
        return instance;
    }

    private static Logger logger = LoggerFactory.getLogger(SqlServerSplitter.class);

    @Override
    public Queue<Integer[]> split(MappingTask mappingTask) {
        // 总数据量
        int total = mappingTask.getSourceMapping().getRowCount();
        // 完成进度(必须大于等于0)
        int completed = mappingTask.getProcessCompleted();
        // 任务上线值，默认10W，建议大于batchNum
        int maxTask = mappingTask.getMaxTask();
        // 每次批量执行数(必须大于0)
        int batchNum = mappingTask.getBatchNum();
        logger.info("Total:" + total);
        logger.info("Completed progress:" + completed);

        // 计算本次任务总量
        int t_start = completed * maxTask;
        int t_end = t_start + maxTask;
        t_end = t_end >= total ? total : t_end;
        // 所有小任务总量
        int count = t_end - t_start;
        logger.info("Max:" + maxTask);
        logger.info("Current:" + count);
        logger.info("Batch:" + batchNum);

        // 计算上次任务页数
        int pageIndex = 0;
        if (0 < completed) {
            pageIndex = t_start % batchNum == 0 ? t_start / batchNum : t_start / batchNum + 1;
        }
        // 计算小任务量
        int taskNum = count % batchNum == 0 ? count / batchNum : count / batchNum + 1;

        // 拆分小任务
        Queue<Integer[]> quene = new ConcurrentLinkedQueue<>();
        for (int i = 0; i < taskNum; i++) {
            quene.offer(new Integer[] { ++pageIndex, batchNum });
        }
        logger.info("Total number of tasks：" + taskNum);
        return quene;
    }

}
